home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmiSoft / Dev / C / Tinygl.lha / TinyGL / src / glut.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-01-22  |  15.2 KB  |  507 lines

  1. // TODO: placer les prototypes dans glut.c
  2.     
  3. #include <stdio.h>
  4. //#include <lib/time.h>
  5.  
  6. #include <proto/timer.h>
  7.  
  8. #include <proto/intuition.h>
  9. #include <proto/graphics.h>
  10. #include <proto/exec.h>
  11.  
  12. #include <dos/dos.h>
  13.  
  14. #include <GL/glut.h>
  15. #include <GL/gla.h>
  16.  
  17. #ifdef __SASC
  18. #include <dos/dos.h>
  19. #include <clib/exec_protos.h>
  20. struct Library *TimerBase = NULL;
  21. #else
  22. #ifdef __MORPHOS__
  23. struct Library *TimerBase = NULL;
  24. #else
  25. struct Device *TimerBase = NULL;
  26. #endif
  27. #endif
  28.  
  29. //#define __isMouseEvent(a) a >= EV_MOUSEEVENTS && a < EV_MOUSEEVENTS+6
  30. //#define __isKeyEvent(a) a >= EV_KEYBOARDEVENTS && a < EV_KEYBOARDEVENTS+3
  31.  
  32. //#define SIGBREAKF_CTRL_C   (1<<12)
  33.  
  34. struct GfxBase *GfxBase = NULL;
  35. struct IntuitionBase *IntuitionBase = NULL;
  36. struct Library *CyberGfxBase = NULL;
  37.  
  38. typedef struct {
  39.     int x, y, width, height, depth;
  40.     struct Window *win;
  41.     GLboolean redisplay;
  42.     GLboolean reshape;
  43. } glut_window_t;
  44.  
  45. // Ajouter un __glut_state : quoique, il y a un windowCreated
  46. // ou __glut_initialized
  47.  
  48. //static glut_ave_t __glut_ave;
  49. static int __glut_initX = 0, __glut_initY = 0;
  50. static int __glut_initWidth = 320, __glut_initHeight = 256, __glut_initDepth = 8;
  51. static int __glut_mouseX = 0, __glut_mouseY = 0;
  52. static glut_window_t __glut_window;
  53. static GLAContext __glut_ctx = NULL;
  54. static int __glut_currWindow = 0;
  55. //static int __glut_numWindows = 0;
  56. static struct timeval __glut_initTime;
  57. static GLboolean __glut_fullScreen = GL_FALSE;
  58. static GLboolean __glut_windowCreated = GL_FALSE;
  59. //static char* __glut_windowName;
  60. static struct Screen *__glut_screen = NULL;
  61. static struct timerequest __glut_timeRequest;
  62.  
  63. typedef void (*glut_displayFunc_t)(void);
  64. typedef void (*glut_idleFunc_t)(void);
  65. typedef void (*glut_keyboardFunc_t)(unsigned char key, int x, int y);
  66. typedef void (*glut_reshapeFunc_t)(int width, int height);
  67.  
  68. static glut_displayFunc_t __glut_displayFunc = NULL;
  69. static glut_idleFunc_t __glut_idleFunc = NULL;
  70. static glut_keyboardFunc_t __glut_keyboardFunc = NULL;
  71. static glut_reshapeFunc_t __glut_reshapeFunc = NULL;
  72.  
  73. static int ProcessMessages(struct Window *WinHandle);
  74.     
  75. // Auxiliary functions
  76.  
  77. void __setupWindow() {
  78.     if (__glut_fullScreen) {
  79.         __glut_window.width = __glut_initWidth = glutGet(GLUT_SCREEN_WIDTH);
  80.         __glut_window.height = __glut_initHeight = glutGet(GLUT_SCREEN_HEIGHT);
  81.         __glut_window.x = __glut_window.y = 0;
  82.     }
  83.  
  84.     // Changer la position de la fenêtre
  85.  
  86.  
  87.     //glAMakeCurrent(__glut_window.win, __glut_ctx);
  88.     __glut_windowCreated = GL_TRUE;
  89. }
  90.  
  91.  
  92. // GLUT API Functions
  93.  
  94. void glutInit(int *argcp, char **argv) {
  95.     int error;
  96.  
  97. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39L);
  98. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39L);
  99.  
  100.    
  101.     CyberGfxBase = (struct Library *)OpenLibrary("cybergraphics.library", 41L);
  102.  
  103.     if (__glut_ctx != NULL) {
  104.             return;
  105.     }
  106.  
  107.     error = OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *) &__glut_timeRequest, 0);
  108. #ifdef __SASC
  109.         TimerBase = (struct Library *)__glut_timeRequest.tr_node.io_Device;
  110. #else
  111. #ifdef __MORPHOS__
  112.         TimerBase = (struct Library *)__glut_timeRequest.tr_node.io_Device;
  113. #else
  114.         TimerBase = __glut_timeRequest.tr_node.io_Device;
  115. #endif
  116. #endif
  117.     GetSysTime(&__glut_initTime);
  118.     
  119.   __glut_ctx = glACreateContext();
  120. }
  121.     
  122.  
  123. // TODO: Contrôler que ça ne sort pas de l'écran
  124. void glutInitWindowPosition(int x, int y) {
  125.     __glut_window.x = __glut_initX = x;
  126.     __glut_window.y = __glut_initY = y;
  127. }
  128.  
  129.  
  130. // TODO: S'assurer que la largeur soit multiple de 4 (ou 8 ?)
  131. void glutInitWindowSize(int width, int height) {
  132.     __glut_window.width = __glut_initWidth = width;
  133.     __glut_window.height = __glut_initHeight = height;
  134. }
  135.  
  136.                                                                                                             
  137. // TODO : Codes d'erreur
  138. // renseigner __glut_window.depth = GetBitMapAttr(window->BitMap, BMA_DEPTH);
  139. // Il semble que si la fct s'exécute bien, elle retourne 1
  140. int glutCreateWindow(char *name) {
  141.     struct Screen *screen = NULL;
  142.     unsigned long modeID = INVALID_ID;
  143.     struct Screen   *WbScreen;
  144.  
  145.         // Workbench depth
  146.         WbScreen = LockPubScreen("Workbench");
  147.         if (WbScreen){
  148.             if (CyberGfxBase){
  149.                 __glut_initDepth = GetCyberMapAttr(WbScreen->RastPort.BitMap, CYBRMATTR_DEPTH);
  150.             }else{
  151.                 __glut_initDepth = GetBitMapAttr(WbScreen->RastPort.BitMap, BMA_DEPTH);
  152.             }
  153.             UnlockPubScreen(NULL, WbScreen);
  154.         }
  155.  
  156. //printf("__glut_initDepth : %d\n", __glut_initDepth);
  157.     if (__glut_initDepth < 8){
  158.         __glut_initDepth = 8;
  159.                 __glut_fullScreen = GL_TRUE;
  160.     }
  161.                                             
  162.         // Best ModeID
  163.     if (CyberGfxBase){
  164.                 modeID = BestCModeIDTags(CYBRBIDTG_Depth, __glut_initDepth,
  165.                                                                 CYBRBIDTG_NominalWidth, __glut_initWidth,
  166.                                                                 CYBRBIDTG_NominalHeight, __glut_initHeight,
  167.                                                                 TAG_DONE);
  168.         }
  169.    
  170.     if (modeID == (unsigned long)INVALID_ID){
  171.         modeID = BestModeID(
  172.                 BIDTAG_NominalWidth, __glut_initWidth,
  173.                 BIDTAG_NominalHeight, __glut_initHeight,
  174.                 BIDTAG_Depth, __glut_initDepth,
  175.                                 BIDTAG_MonitorID, (ULONG)(GetVPModeID(&WbScreen->ViewPort) & MONITOR_ID_MASK),
  176.                                 TAG_END);
  177.     }
  178.  
  179.     if (modeID == (unsigned long)INVALID_ID){
  180.         return 0;
  181.     }
  182.                                                                                                         
  183.  
  184.         // Open the display
  185.         if (__glut_fullScreen == GL_TRUE){
  186. //printf("glut full screen\n");
  187.         screen = OpenScreenTags(NULL,
  188.                                      SA_Width, __glut_initWidth,
  189.                                      SA_Height, __glut_initHeight,
  190.                                      SA_Depth, __glut_initDepth,
  191.                                      SA_Title, (ULONG)"TinyGL",
  192.                                      SA_ShowTitle, FALSE,
  193.                                      SA_Type, CUSTOMSCREEN,
  194.                                      SA_SharePens, TRUE,
  195.                                      SA_DisplayID, modeID,
  196.                                      SA_Interleaved, TRUE,
  197.                                                 SA_FullPalette, __glut_initDepth == 8,
  198.                                      TAG_DONE);
  199.         if (screen == NULL){
  200.             return 0;
  201.         }
  202.         
  203.         __glut_screen = screen;
  204.                                                         
  205.         __glut_window.win = OpenWindowTags(NULL,
  206.                         WA_Left, __glut_initX,
  207.                         WA_Top, __glut_initY,
  208.                         WA_Width, __glut_initWidth,
  209.                         WA_Height, __glut_initHeight,
  210.                         WA_CustomScreen, (ULONG)screen,
  211.                         //WA_RMBTrap, TRUE,
  212.                                                 WA_CloseGadget, FALSE,
  213.                                                 WA_DepthGadget, FALSE,
  214.                                                 WA_Activate, TRUE,
  215.                         WA_Title, (unsigned long)name,
  216.                         WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_ACTIVEWINDOW| IDCMP_IDCMPUPDATE | IDCMP_CHANGEWINDOW | IDCMP_NEWSIZE | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_VANILLAKEY | IDCMP_RAWKEY, // | IDCMP_INTUITICKS | IDCMP_NEWSIZE,
  217.                                                 WA_Flags, WFLG_SIZEGADGET | WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET, // | WFLG_REPORTMOUSE,
  218.                                                 TAG_DONE);
  219.  
  220.     }else{
  221.         __glut_screen = WbScreen;
  222.                                                     
  223.         // TODO : changer initX et initY dans le cas de fenêtre sur Wb
  224.         // voir si les flags et IDCMP sont ok
  225.         __glut_window.win = OpenWindowTags(NULL,
  226.                         WA_Left, __glut_initX,
  227.                         WA_Top, __glut_initY,
  228.                         WA_InnerWidth, __glut_initWidth,
  229.                         WA_InnerHeight, __glut_initHeight,
  230.                         WA_CustomScreen, (ULONG)WbScreen,
  231.                         WA_SizeGadget, FALSE,
  232.                                 WA_CloseGadget, TRUE,
  233.                         WA_RMBTrap, TRUE,
  234.                         //WA_CloseGadget, TRUE,
  235.                         //WA_DepthGadget, TRUE,
  236.                                 WA_Activate, TRUE,
  237.                         WA_Title, (unsigned long)name,
  238.                         WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_ACTIVEWINDOW| IDCMP_IDCMPUPDATE | IDCMP_CHANGEWINDOW | IDCMP_NEWSIZE | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_VANILLAKEY | IDCMP_RAWKEY, // | IDCMP_INTUITICKS | IDCMP_NEWSIZE,
  239.                                 WA_Flags, WFLG_SIZEGADGET | WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET, // | WFLG_REPORTMOUSE,
  240.                                 TAG_DONE);
  241.     }
  242.    
  243.     // TODO : __glut_window.depth ne doit pas servir ... vérifier et enlever
  244.     __glut_window.depth = GetBitMapAttr(__glut_window.win->RPort->BitMap, BMA_DEPTH);
  245.  
  246.     glAMakeCurrent(__glut_window.win, __glut_ctx);
  247.  
  248.         __glut_window.redisplay = GL_TRUE;
  249.     __glut_window.reshape = GL_TRUE;
  250.  
  251.  
  252.     return 1;
  253. }
  254.  
  255.  
  256. void glutSwapBuffers(void) {
  257.     glASwapBuffers(__glut_window.win);
  258. }
  259.  
  260.  
  261. void glutFullScreen(void) {
  262.     __glut_fullScreen = GL_TRUE;
  263.         //__setupWindow();
  264. }
  265.  
  266.  
  267. void glutSetWindow(int win) {
  268.     __glut_currWindow = win;
  269. }
  270.  
  271.  
  272. int glutGetWindow(void) {
  273.     return __glut_currWindow;
  274. }
  275.  
  276.  
  277. void glutDestroyWindow(int win) {
  278.     
  279.     glADestroyContext(__glut_ctx);
  280.     CloseWindow(__glut_window.win);
  281.     __glut_window.win = NULL;
  282.     __glut_windowCreated = GL_FALSE;
  283.  
  284.         // Close the screen only if it's a private one
  285.         if (__glut_fullScreen == GL_TRUE){
  286.             CloseScreen(__glut_screen);
  287.             __glut_screen = NULL;
  288.         }
  289. }
  290.  
  291.  
  292. // Afficher la fenêtre si
  293. //          __glut_displayFunc();
  294. //          __glut_window.redisplay = GL_FALSE;
  295. // TODO: passer les coordonnées du pointeur souris à keyboard()
  296. void glutMainLoop(void) {
  297.     struct Window *WinHandle = NULL;
  298.     int done = 0;
  299.     ULONG signals;
  300.    
  301.         if (__glut_windowCreated == GL_FALSE) {
  302.         __setupWindow();
  303.     }
  304.  
  305.     if ((__glut_window.reshape) && (__glut_reshapeFunc != NULL)){
  306.         __glut_reshapeFunc(__glut_window.width, __glut_window.height);
  307.         __glut_window.reshape = GL_FALSE;
  308.     }
  309.                                     
  310.  
  311.     // Récupération du handle de fenêtre et boucle des messages
  312.    
  313.     WinHandle = __glut_window.win;
  314.  
  315.         //WaitPort(MyWindow->UserPort);
  316.         //MyWinMsg = (struct IntuiMessage *) GetMsg(MyWindow->UserPort);
  317.  
  318.         while (done == 0){
  319.                         
  320.             signals = SetSignal(0L, 0L);
  321.             if (signals & (1L << WinHandle->UserPort->mp_SigBit)){
  322.                     done = ProcessMessages(WinHandle);
  323.             }
  324.  
  325.  
  326.             // Comme pour keyboardFunc, vérifier aussi que displayFunc n'est pas NULL
  327.             // Idem pour reshapeFunc
  328.  
  329.             if ((__glut_window.redisplay) && (__glut_displayFunc != NULL)){
  330.                 __glut_displayFunc();
  331.                 __glut_window.redisplay = GL_FALSE;
  332.             }
  333.             if ((__glut_window.reshape) && (__glut_reshapeFunc != NULL)){
  334.                                 __glut_reshapeFunc(__glut_window.width, __glut_window.height);
  335.                                 __glut_window.reshape = GL_FALSE;
  336.             }
  337.         
  338.             // A chaque tour de boucle on exécute la fonction idle
  339.             if (__glut_idleFunc != NULL) {
  340.                 __glut_idleFunc();
  341.             }
  342.  
  343.         } // ici, done = 1, on sort de la boucle
  344.  
  345.     
  346.     // Fermeture
  347.     glutDestroyWindow(0);
  348.                                         
  349.     if (CyberGfxBase){
  350.         CloseLibrary(CyberGfxBase);
  351.     }
  352.  
  353. if (GfxBase){
  354.     CloseLibrary((struct Library *)GfxBase);
  355. }
  356. if (IntuitionBase){
  357.     CloseLibrary((struct Library *)IntuitionBase);
  358. }
  359.     
  360.     CloseDevice((struct IORequest *) &__glut_timeRequest);
  361. }
  362.  
  363.  
  364. void glutPostRedisplay(void) {
  365.     __glut_window.redisplay = GL_TRUE;
  366. }
  367.  
  368.  
  369. void glutDisplayFunc(void (*func)(void)) {
  370.     __glut_displayFunc = func;
  371. }
  372.  
  373.  
  374. void glutReshapeFunc(void (*func)(int width, int height)) {
  375.     __glut_reshapeFunc = func;
  376. }
  377.  
  378.  
  379. void glutIdleFunc(void (*func)(void)) {
  380.     __glut_idleFunc = func;
  381. }
  382.  
  383.  
  384. void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)) {
  385.     __glut_keyboardFunc = func;
  386. }
  387.  
  388. int glutGet(GLenum state) {
  389.     struct timeval thetime;
  390.  
  391.     switch (state) {
  392.     case GLUT_WINDOW_X :
  393.         return __glut_window.x;
  394.     case GLUT_WINDOW_Y :
  395.         return __glut_window.y;
  396.     case GLUT_WINDOW_WIDTH :
  397.         return __glut_window.width;
  398.     case GLUT_WINDOW_HEIGHT :
  399.         return __glut_window.height;
  400.     case GLUT_WINDOW_DEPTH_SIZE :
  401.         return __glut_window.depth;
  402.     case GLUT_WINDOW_PARENT :
  403.         return 0;
  404.     case GLUT_WINDOW_NUM_CHILDREN :
  405.         return 0;
  406.     case GLUT_SCREEN_WIDTH :
  407.         return __glut_window.win->WScreen->Width;
  408.     case GLUT_SCREEN_HEIGHT :
  409.         return __glut_window.win->WScreen->Height;
  410.     case GLUT_SCREEN_WIDTH_MM :
  411.         return 0;
  412.     case GLUT_SCREEN_HEIGHT_MM :
  413.         return 0;
  414.     case GLUT_INIT_WINDOW_X :
  415.         return __glut_initX;
  416.     case GLUT_INIT_WINDOW_Y :
  417.         return __glut_initY;
  418.     case GLUT_INIT_WINDOW_WIDTH :
  419.         return __glut_initWidth;
  420.     case GLUT_INIT_WINDOW_HEIGHT :
  421.         return __glut_initHeight;
  422.     case GLUT_ELAPSED_TIME :
  423.         GetSysTime(&thetime);
  424.         SubTime(&thetime, &__glut_initTime); /* Now thetime contains the elapsed time */
  425.         return (int)((thetime.tv_secs*1000) + (thetime.tv_micro / 1000));
  426.     }
  427.  
  428.     return -1;
  429. }
  430.  
  431. /// Not implemented
  432. void glutInitDisplayMode(unsigned int mode) {}
  433.  
  434.  
  435. static int ProcessMessages(struct Window *WinHandle){
  436.     int done = 0;
  437.     ULONG portsig, waitsigs;
  438.     struct IntuiMessage *imsg = NULL;
  439.  
  440.             portsig = 1L << WinHandle->UserPort->mp_SigBit;
  441.  
  442.       waitsigs = Wait(portsig | SIGBREAKF_CTRL_C);
  443.       if (waitsigs & portsig){
  444.         while (imsg = (struct IntuiMessage *)GetMsg(WinHandle->UserPort)){
  445.  
  446.           switch (imsg->Class){
  447.             case IDCMP_CLOSEWINDOW:
  448.               done = 1;
  449.               break;
  450.             case IDCMP_IDCMPUPDATE:
  451.                             //printf("IDCMPUPDATE\n");
  452.               break;
  453.             case IDCMP_VANILLAKEY:
  454.                             // TODO: passer les coordonnées à la place de (0,0)
  455.                             //printf("Code VANILLAKEY = %d\n", imsg->Code);
  456.               if (imsg->Code == 27){
  457.                                     done = 1;
  458.               }else{
  459.                                     if (__glut_keyboardFunc){
  460.                                             __glut_keyboardFunc(imsg->Code, 0, 0);
  461.                                     }
  462.               }
  463.               break;
  464.             case IDCMP_NEWSIZE:
  465.                             //printf("NEWSIZE\n");
  466.               break;
  467.             case IDCMP_MOUSEMOVE:
  468.                             //__glut_mouseX = ave_event.msg->EVD_X;
  469.                             //__glut_mouseY = ave_event.msg->EVD_Y;
  470.                             //printf("MOUSEMOVE\n");
  471.               break;
  472.             case IDCMP_CHANGEWINDOW:
  473.                             //printf("CHANGEWINDOW\n");
  474.               break;
  475.             case IDCMP_REFRESHWINDOW:
  476.                             //printf("REFRESHWINDOW\n");
  477.               break;
  478.             case IDCMP_ACTIVEWINDOW:
  479.                             //printf("ACTIVEWINDOW\n");
  480.               break;
  481.                         case IDCMP_MOUSEBUTTONS:
  482.                             //case IECODE_LBUTTON:
  483.  
  484.                             break;
  485.             case IDCMP_RAWKEY:
  486.                             // Code 45 : escape
  487.                             //printf("RAWKEY\n");
  488.                             //printf("Code RAWKEY = %d\n", imsg->Code);
  489.                             if (__glut_keyboardFunc != NULL) {
  490.                                 __glut_keyboardFunc(imsg->Code, 0, 0);
  491.                             }
  492.               break;
  493.                         //default:
  494.                             //printf("IDCMP_default\n");
  495.           }
  496.                     ReplyMsg((struct Message *)imsg);
  497.         }
  498.       }
  499.       if (waitsigs & SIGBREAKF_CTRL_C){
  500.         done = 1;
  501.       }
  502.                                             
  503.     return done;
  504. }
  505.     
  506.  
  507.